import { defineComponent, PropType, Ref, ref, VNode, watch } from 'vue';
import { useControlController, useNamespace } from '@ibiz-template/vue3-util';
import {
  IAppDEUIActionGroupDetail,
  IDEContextMenu,
  IDETBUIActionItem,
  IDETreeNode,
} from '@ibiz/model-core';
import './context-menu.scss';
import { ContextMenuController, ITreeNodeData } from '@ibiz-template/runtime';
import { showTitle } from '@ibiz-template/core';

export const ContextMenuControl = defineComponent({
  name: 'IBizContextMenuControl',
  props: {
    modelData: {
      type: Object as PropType<IDEContextMenu>,
      required: true,
    },
    context: { type: Object as PropType<IContext>, required: true },
    params: { type: Object as PropType<IParams>, default: () => ({}) },
    // 模式
    mode: {
      type: String as PropType<'dropdown' | 'buttons'>,
      default: 'buttons',
    },
    // 分组的行为级别
    groupLevelKeys: {
      type: Object as PropType<number[]>,
      // eslint-disable-next-line vue/require-valid-default-prop
      default: [50],
    },
    // 节点数据
    nodeData: {
      type: Object as PropType<ITreeNodeData>,
      required: true,
    },
    // 节点模型
    nodeModel: {
      type: Object as PropType<IDETreeNode>,
      required: true,
    },
  },
  setup(props, { emit }) {
    const c = useControlController(
      (...args) => new ContextMenuController(...args),
    );

    const ns = useNamespace('context-menu');

    const actionDetails = props.modelData.detoolbarItems as IDETBUIActionItem[];

    // 平铺行为
    const expandDetails: Ref<IDETBUIActionItem[]> = ref([]);

    // 分组行为
    const groupDetails: Ref<IDETBUIActionItem[]> = ref([]);

    const groupButtonRef = ref();

    // 下拉列表ref
    const dropdownRef = ref();

    const popoverVisible = ref(false);

    // 转换多语言
    const transformLanguage = (items?: IDETBUIActionItem[]) => {
      if (!Array.isArray(items)) {
        return;
      }
      items.forEach(detail => {
        if (detail.capLanguageRes && detail.capLanguageRes.lanResTag) {
          detail.caption = ibiz.i18n.t(
            detail.capLanguageRes.lanResTag,
            detail.caption,
          );
        }
        if (detail.tooltipLanguageRes && detail.tooltipLanguageRes.lanResTag) {
          detail.tooltip = ibiz.i18n.t(
            detail.tooltipLanguageRes.lanResTag,
            detail.tooltip,
          );
        }
        transformLanguage(detail.detoolbarItems);
      });
    };

    if (actionDetails) {
      // 转换多语言
      transformLanguage(actionDetails);

      // 根据level分组
      actionDetails.forEach(detail => {
        if (
          !detail.actionLevel ||
          props.groupLevelKeys.findIndex(
            item => item === detail.actionLevel,
          ) !== -1
        ) {
          groupDetails.value.push(detail);
        } else {
          expandDetails.value.push(detail);
        }
      });
    }

    const calcActionItemClass = (item: IDETBUIActionItem) => {
      const { actionLevel } = item;
      return [
        ns.e('item'),
        ns.is('disabled', false),
        ns.em('item', `level-${actionLevel}`),
      ];
    };

    watch(
      () => props.nodeData,
      async (newVal, oldVal) => {
        if (newVal !== oldVal) {
          await c.calcButtonState(
            newVal._deData || (newVal.srfkey ? newVal : undefined),
            props.nodeModel.appDataEntityId,
          );
        }
      },
    );

    c.evt.on('onCreated', async () => {
      await c.calcButtonState(
        props.nodeData._deData ||
          (props.nodeData.srfkey ? props.nodeData : undefined),
        props.nodeModel.appDataEntityId,
      );
    });

    // 点击事件抛给表格执行
    const handleClick = async (
      detail: IDETBUIActionItem,
      e: MouseEvent,
    ): Promise<void> => {
      if (props.mode === 'buttons') {
        popoverVisible.value = false;
      } else if (dropdownRef.value) {
        dropdownRef.value.handleClose();
      }
      e.stopPropagation();
      popoverVisible.value = false;
      emit('action-click', detail, e);
    };

    return {
      c,
      ns,
      expandDetails,
      groupDetails,
      groupButtonRef,
      dropdownRef,
      popoverVisible,
      handleClick,
      calcActionItemClass,
      actionDetails,
    };
  },
  render() {
    const details = this.actionDetails || [];

    const renderDivider = (isExpand: boolean) => {
      return (
        <el-divider
          class={this.ns.e('separator')}
          border-style='double'
          direction={isExpand ? 'vertical' : 'horizontal'}
        />
      );
    };

    const renderActions = (items: IDETBUIActionItem[], isExpand = true) => {
      return items.map(detail => {
        if (!this.c.state.buttonsState[detail.id!]?.visible) {
          return null;
        }
        if (detail.itemType === 'SEPERATOR') {
          return renderDivider(isExpand);
        }
        if (
          detail.itemType === 'DEUIACTION' ||
          (detail.itemType === 'ITEMS' && !detail.detoolbarItems?.length)
        ) {
          return [
            (detail as IAppDEUIActionGroupDetail).addSeparator &&
              renderDivider(isExpand),
            <el-button
              text
              size='small'
              onClick={(e: MouseEvent): Promise<void> =>
                this.handleClick(detail, e)
              }
              title={showTitle(detail.tooltip)}
              disabled={this.c.state.buttonsState[detail.id!].disabled}
              class={this.calcActionItemClass(detail)}
            >
              <div class={this.ns.e('action-content')}>
                {detail.showIcon && detail.sysImage && (
                  <div class={this.ns.e('action-content-icon')}>
                    <iBizIcon icon={detail.sysImage}></iBizIcon>
                  </div>
                )}

                {detail.showCaption ? (
                  <div class={this.ns.e('action-content-caption')}>
                    {detail.caption}
                  </div>
                ) : (
                  ''
                )}
              </div>
            </el-button>,
          ];
        }
        if (detail.itemType === 'ITEMS') {
          return (
            <el-popover
              placement='right-start'
              popper-class={this.ns.e('popover')}
              teleported={false}
            >
              {{
                reference: () => {
                  return [
                    (detail as IAppDEUIActionGroupDetail).addSeparator &&
                      renderDivider(isExpand),
                    <el-button
                      text
                      size='small'
                      onClick={(e: MouseEvent): Promise<void> =>
                        this.handleClick(detail, e)
                      }
                      title={showTitle(detail.tooltip)}
                      disabled={this.c.state.buttonsState[detail.id!].disabled}
                      class={this.calcActionItemClass(detail)}
                    >
                      <div class={this.ns.e('action-content')}>
                        {detail.showIcon && detail.sysImage && (
                          <div class={this.ns.e('action-content-icon')}>
                            <iBizIcon icon={detail.sysImage}></iBizIcon>
                          </div>
                        )}

                        {detail.showCaption ? (
                          <div
                            class={[
                              this.ns.e('action-content-caption'),
                              this.ns.e('action-content-group-caption'),
                            ]}
                          >
                            {detail.caption}
                          </div>
                        ) : (
                          ''
                        )}
                        <ion-icon
                          class={this.ns.e('action-content-group-icon')}
                          name='chevron-forward-outline'
                        ></ion-icon>
                      </div>
                    </el-button>,
                  ];
                },
                default: () => {
                  return renderActions(detail.detoolbarItems || [], isExpand);
                },
              }}
            </el-popover>
          );
        }
        return null;
      });
    };

    const renderGroup = () => {
      if (this.groupDetails.length === 0) {
        return null;
      }
      // 子项所有项都隐藏，父项也应该隐藏
      const pvisible =
        this.groupDetails.findIndex(item => {
          return this.c.state.buttonsState[item.id!].visible === true;
        }) !== -1;
      if (!pvisible) {
        return null;
      }
      // 当前项禁用或子项所有项都禁用，父项也应该禁用
      const pdisabled =
        this.groupDetails.findIndex(item => {
          return this.c.state.buttonsState[item.id!].disabled === false;
        }) === -1;
      return [
        <el-button
          size='small'
          text
          disabled={pdisabled}
          ref='groupButtonRef'
          class={[this.ns.e('item'), this.ns.is('expand', this.popoverVisible)]}
        >
          {{
            icon: () => (
              <ion-icon class={this.ns.e('icon')} name='ellipsis-vertical' />
            ),
          }}
        </el-button>,
        <el-popover
          placement='bottom-start'
          virtual-ref={this.groupButtonRef}
          trigger='click'
          v-model:visible={this.popoverVisible}
          popper-class={this.ns.e('popover')}
          virtual-triggering
          transition='none'
        >
          {renderActions(this.groupDetails, false)}
        </el-popover>,
      ];
    };

    if (!this.c.state.buttonsState.visible) {
      return;
    }

    if (this.mode === 'buttons') {
      // 按钮模式
      return (
        <div
          class={[this.ns.b(), this.ns.m('buttons')]}
          onClick={(e): void => e.stopPropagation()}
        >
          {renderActions(this.expandDetails)}
          {renderGroup()}
        </div>
      );
    }
    // 下拉模式
    return (
      <el-dropdown
        ref='dropdownRef'
        onCommand={(command: IAppDEUIActionGroupDetail): Promise<void> =>
          this.handleClick(command, new MouseEvent('click'))
        }
        class={[this.ns.b(), this.ns.m('dropdown')]}
      >
        {{
          default: (): VNode => (
            <span class={this.ns.e('caption')}>
              <ion-icon
                class={this.ns.e('caption-icon')}
                name='ibiz-arrow-down'
              />
            </span>
          ),
          dropdown: (): VNode => (
            <el-dropdown-menu>
              {details.length > 0 &&
                details.map(detail => {
                  if (this.c.state.buttonsState[detail.id!]?.visible) {
                    return (
                      <el-dropdown-item
                        class={[
                          this.ns.e('item'),
                          this.ns.is('disabled', false),
                        ]}
                        title={showTitle(detail.tooltip)}
                        disabled={
                          this.c.state.buttonsState[detail.id!].disabled
                        }
                        command={detail}
                      >
                        {detail.showIcon && detail.sysImage && (
                          <iBizIcon icon={detail.sysImage}></iBizIcon>
                        )}
                        {detail.showCaption ? detail.caption : ''}
                      </el-dropdown-item>
                    );
                  }
                  return null;
                })}
            </el-dropdown-menu>
          ),
        }}
      </el-dropdown>
    );
  },
});
